package com.wzx.core.aop.invoke;

import com.wzx.core.aop.AdviceClassRegister;
import com.wzx.core.aop.constant.AdviceType;
import com.wzx.core.ioc.context.AbstractApplicationContext;
import com.wzx.core.ioc.proxy.Invocation;

import java.lang.reflect.Method;
import java.util.List;

public class AopInvocation extends Invocation {

    private AbstractApplicationContext context;
    private AdviceClassRegister adviceClassRegister;
    private Object originObject;
    private String originObjectClassName;

    public AopInvocation(Object originObject, AbstractApplicationContext context, AdviceClassRegister adviceClassRegister) {
        this.originObject = originObject;
        this.originObjectClassName = originObject.getClass().getName();
        this.context = context;
        this.adviceClassRegister = adviceClassRegister;
    }

    @Override
    protected void before(Object o, Method method, Object[] objects) {
        this.proceed(AdviceType.BEFORE, this.originObject, o, method, objects, null, null);
    }

    @Override
    protected void after(Object o, Method method, Object[] objects) {
        this.proceed(AdviceType.AFTER, this.originObject, o, method, objects, null, null);
    }

    @Override
    protected void running(Object o, Method method, Object[] objects, Object retVal) {
        this.proceed(AdviceType.RUNNING, this.originObject, o, method, objects, retVal, null);
    }

    @Override
    protected void throwing(Object o, Method method, Object[] objects, Throwable ex) {
        this.proceed(AdviceType.THROWING, this.originObject, o, method, objects, null, ex);
    }


    private void proceed(AdviceType type, Object originObject, Object proxyObject, Method method, Object[] objects, Object retVal, Throwable ex) {
        List<AspectLogic> aspectLogic = adviceClassRegister
                .createAspectLogic(originObjectClassName, method.getName(), type);
        if (aspectLogic == null) {
            return;
        }
        for (AspectLogic logic : aspectLogic) {
            logic.proceed(originObject, method, objects, retVal, ex);
        }
    }

    @Override
    protected Object getOriginObject() {
        return this.originObject;
    }
}
